package com.demo2do.fms.admin.service.report.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.demo2do.core.entity.page.Page;
import com.demo2do.core.persistence.GenericDaoSupport;
import com.demo2do.core.persistence.annotation.Dao;
import com.demo2do.core.persistence.support.QueryFilter;
import com.demo2do.core.utils.CollectionUtils;
import com.demo2do.fms.admin.dao.business.TransportCostDao;
import com.demo2do.fms.admin.dao.vehicle.VehicleSourceDao;
import com.demo2do.fms.admin.entity.export.report.TransportToolSheet;
import com.demo2do.fms.admin.entity.report.report.DriverAccumulatedMileageReportSearch;
import com.demo2do.fms.admin.entity.report.report.DriverCostReportSearch;
import com.demo2do.fms.admin.entity.report.report.TransportRevenueScheduleReportSearch;
import com.demo2do.fms.admin.entity.report.report.VehicleAccumulatedMileageReportSearch;
import com.demo2do.fms.admin.entity.search.report.TransportToolSearch;
import com.demo2do.fms.admin.handler.support.FmsJdbcSupport;
import com.demo2do.fms.admin.service.report.ReportService;
import com.demo2do.fms.entity.supplier.common.Supplier;
import com.demo2do.fms.entity.vehicle.source.VehicleSource;
import com.demo2do.fms.entity.vehicle.tractor.Tractor;
import com.demo2do.fms.entity.vehicle.trailer.Trailer;

/**
 *
 * @author Ark
 *
 */
@Service("reportService")
public class ReportServiceImpl implements ReportService {
	
	@Dao
	private TransportCostDao transportCostDao;

	@Dao
	private VehicleSourceDao vehicleSourceDao;
	
	@Autowired
	private FmsJdbcSupport fmsJdbcSupport;
	
	@Autowired
	private GenericDaoSupport genericDaoSupport;
	
	/* (non-Javadoc)
	 * @see com.demo2do.fms.admin.service.report.ReportService#count(com.demo2do.fms.admin.entity.report.report.VehicleAccumulatedMileageReportSearch)
	 */
	public int count(VehicleAccumulatedMileageReportSearch search) {
	    String sentence = search.buildCountTemplate();
        Map<String, Object> parameters = search.buildParameters();
		return fmsJdbcSupport.queryForInt(sentence, parameters);
	}
	
	/* (non-Javadoc)
	 * @see com.demo2do.fms.admin.service.report.ReportService#search(com.demo2do.fms.admin.entity.search.report.VehicleAccumulatedMileageSearch, com.demo2do.core.entity.page.Page)
	 */
	public List<Map<String, Object>> search(VehicleAccumulatedMileageReportSearch search, Page page) {
		
	    // 1. calculate page
        Integer beginIndex = page.getBeginIndex() + 1;
        search.setBeginIndex(beginIndex);
        
        Integer endIndex = page.getCurrentPage() * page.getEveryPage();
        search.setEndIndex(endIndex);
        
        // 2. build parameters
        String sentence = search.buildSentenceTemplate();
        Map<String, Object> parameters = search.buildParameters();
        
        // 3. do query
        List<Map<String, Object>> result = fmsJdbcSupport.queryForList(sentence, parameters, search.buildRowMapper());
        page.calculate();
        return result;
		
	}
	
	/* (non-Javadoc)
	 * @see com.demo2do.fms.admin.service.report.ReportService#count(com.demo2do.fms.admin.entity.search.report.DriverAccumulatedMileageSearch)
	 */
	public int count(DriverAccumulatedMileageReportSearch search) {
		String sentence = search.buildCountTemplate();
		Map<String, Object> parameters = search.buildParameters();
		return fmsJdbcSupport.queryForInt(sentence, parameters);
	}
	
	/* (non-Javadoc)
	 * @see com.demo2do.fms.admin.service.report.ReportService#search(com.demo2do.fms.admin.entity.search.report.DriverAccumulatedMileageSearch, com.demo2do.core.entity.page.Page)
	 */
	public List<Map<String, Object>> search(DriverAccumulatedMileageReportSearch search, Page page) {
		
	    // 1. calculate page
	    Integer beginIndex = page.getBeginIndex() + 1;
	    search.setBeginIndex(beginIndex);
	    
	    Integer endIndex = page.getCurrentPage() * page.getEveryPage();
	    search.setEndIndex(endIndex);
	    
		// 2. build parameters
		String sentence = search.buildSentenceTemplate();
		Map<String, Object> parameters = search.buildParameters();
		
		// 3. do query
		List<Map<String, Object>> result = fmsJdbcSupport.queryForList(sentence, parameters, search.buildRowMapper());
		page.calculate();
		return result;
		
	}
	
	/* (non-Javadoc)
	 * @see com.demo2do.fms.admin.service.report.ReportService#count(com.demo2do.fms.admin.entity.report.report.DriverCostReportSearch)
	 */
	public int count(DriverCostReportSearch search) {
		String sentence = search.buildCountTemplate();
		Map<String, Object> parameters = search.buildParameters();
		return fmsJdbcSupport.queryForInt(sentence, parameters);
	}
	
	/* (non-Javadoc)
	 * @see com.demo2do.fms.admin.service.report.ReportService#search(com.demo2do.fms.admin.entity.report.report.DriverCostReportSearch, com.demo2do.core.entity.page.Page)
	 */
	public List<Map<String, Object>> search(DriverCostReportSearch search, Page page) {
		
	    // 1. calculate page
        Integer beginIndex = page.getBeginIndex() + 1;
        search.setBeginIndex(beginIndex);
        
        Integer endIndex = page.getCurrentPage() * page.getEveryPage();
        search.setEndIndex(endIndex);
        
        // 1. build parameters
        String sentence = search.buildSentenceTemplate();
        Map<String, Object> parameters = search.buildParameters();
        
        // 2. do query
        List<Map<String, Object>> result = fmsJdbcSupport.queryForList(sentence, parameters, search.buildRowMapper());
        page.calculate();
        return result;
		
	}
	
	/* (non-Javadoc)
	 * @see com.demo2do.fms.admin.service.report.ReportService#count(com.demo2do.fms.admin.entity.search.report.TransportToolSearch)
	 */
	public int count(TransportToolSearch search) {
	    String sentence = search.buildSentenceTemplate();
        Map<String, Object> parameters = search.buildParameters();
        return genericDaoSupport.count(sentence, parameters);
	}
	
	/* (non-Javadoc)
	 * @see com.demo2do.fms.admin.service.report.ReportService#search(com.demo2do.fms.admin.entity.search.report.TransportToolSearch, com.demo2do.core.entity.page.Page)
	 */
	@SuppressWarnings("unchecked")
    public List<TransportToolSheet> search(TransportToolSearch search, Page page) {
	    
	    // 1. build parameters
        String sentence = search.buildSentenceTemplate();
        Map<String, Object> parameters = search.buildParameters();
        
        // 2. do query
        page.calculate();
        List<Supplier> suppliers = genericDaoSupport.searchForList(sentence, parameters, page.getBeginIndex(), page.getEveryPage());

        // 3. construct suppliers to transportTools
        List<TransportToolSheet> transportToolSheets = this.parseTransportToolSheet(suppliers, search);
        return transportToolSheets;
        
	}
	
	/* (non-Javadoc)
	 * @see com.demo2do.fms.admin.service.report.ReportService#export(com.demo2do.fms.admin.entity.search.report.TransportToolSearch)
	 */
	@SuppressWarnings("unchecked")
    public List<TransportToolSheet> export(TransportToolSearch search) {
	    
	    // 1. build parameters
        String sentence = search.buildSentenceTemplate();
        Map<String, Object> parameters = search.buildParameters();
        
        // 2. query and transform to sheet
        List<Supplier> suppliers = genericDaoSupport.searchForList(sentence, parameters);
        List<TransportToolSheet> transportToolSheets = this.parseTransportToolSheet(suppliers, search);
        return transportToolSheets;
	    
	}
	
	/**
	 * @param suppliers
	 * @param search
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "deprecation" })
    public List<TransportToolSheet> parseTransportToolSheet(List<Supplier> suppliers, TransportToolSearch search) {
	    
	    List<TransportToolSheet> tools = new ArrayList<TransportToolSheet>();
	    
	    for (Supplier supplier : suppliers) {
            
	        // 总运力
	        List<VehicleSource> sources = this.listVehicleSource(supplier.getId(), search);
	        int totalVehicles = sources.size();
	        
	        List<Long> tractorIds = CollectionUtils.extractPropertyList(sources, "tractorId");
	        List<Tractor> tractors = new ArrayList<Tractor>();
	        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(tractorIds)) {
	            for (Long tractorId : tractorIds) {
                    if (tractorId != null) {
                        tractors.add(genericDaoSupport.load(Tractor.class, tractorId));
                    }
	            }
	        }
	        
	        List<Long> trailerIds = CollectionUtils.extractPropertyList(sources, "trailerId");
	        List<Trailer> trailers = new ArrayList<Trailer>();
	        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(trailerIds)) {
	            for (Long trailerId : trailerIds) {
	                if (trailerId != null) {
	                    trailers.add(genericDaoSupport.load(Trailer.class, trailerId));
	                }
	            }
	        }
	        
	        // 平均装载量
	        int totalLoads = 0;
	        for (Trailer trailer : trailers) {
	            if (trailer.getTrainload() != null) {
	                totalLoads += trailer.getTrainload().intValue();
	            }
            }
	        int avgLoads = totalVehicles != 0 ? (totalLoads / totalVehicles) : 0;
	        
	        // 1位车型数量
	        int oneLoads = 0;
	        // 2位车型数量
	        int twoLoads = 0;
	        // 6位车型数量
	        int sixLoads = 0;
	        // 7位车型数量
	        int sevenLoads = 0;
	        // 8位车型数量
	        int eightLoads = 0;
	        // 10位车型数量
	        int tenLoads = 0;
	        // 12位车型数量
	        int twelveLoads = 0;
	        // 超过14位车型数量
	        int fourteenLoads = 0;
	        // 其他车型数量
	        int otherLoads = 0;
	        
	        for (Trailer trailer : trailers) {
	            
	            if (trailer.getTrainload() == null) {
	                continue;
	            }
                
	            int trainload = trailer.getTrainload().intValue();
	            
	            if (trainload == 1) {
	                oneLoads++;
	            } else if (trainload == 2) {
	                twoLoads++;
	            } else if (trainload == 6) {
	                sixLoads++;
	            } else if (trainload == 7) {
	                sevenLoads++;
	            } else if (trainload == 8) {
	                eightLoads++;
	            } else if (trainload == 10) {
	                tenLoads++;
	            } else if (trainload == 12) {
	                twelveLoads++;
	            } else if (trainload >= 14) {
	                fourteenLoads++;
	            } else {
	                otherLoads++;
	            }
	            
            }
	        
	        // 平均车龄
	        int totalVehicleAge = 0;
	        for (Tractor tractor : tractors) {
                
	            Date registrationTime = tractor.getRegistrationTime();
                int betweenYears = new Date().getYear() - registrationTime.getYear();
                totalVehicleAge += betweenYears;
	            
            }
	        int avgVehicleAge = tractors.size() != 0 ? (totalVehicleAge / tractors.size()) : 0;
	        
	        // 有效运力
	        int syncVehicles = 0;
	        // 锁定运力
	        int lockVehicles = 0;
	        
	        for (VehicleSource source : sources) {
                
	            if (source.getSynchronize()) {
	                syncVehicles++;
	            }
	            
	            if (source.isLock()) {
	                lockVehicles++;
	            }
	            
            }
	        
	        TransportToolSheet tool = new TransportToolSheet(supplier, totalVehicles, oneLoads, twoLoads, sixLoads, sevenLoads, eightLoads, tenLoads, twelveLoads, fourteenLoads, otherLoads, avgLoads, avgVehicleAge, syncVehicles, lockVehicles);
	        tools.add(tool);
	        
        }
	    
	    return tools;
	    
	}
	
	/**
	 * @param supplierId
	 * @param search
	 * @return
	 */
	@SuppressWarnings("unchecked")
    private List<VehicleSource> listVehicleSource(Long supplierId, TransportToolSearch search) {
	    
	    QueryFilter queryFilter = new QueryFilter();
	    queryFilter.addEquals("supplier", "id", supplierId);
        queryFilter.addEquals("status", search.getStatus());
        queryFilter.addEquals("synchronize", search.getSynchronize());
        
        String sentence = "FROM VehicleSource WHERE disabled = false" + queryFilter.clauseSentence();
        return genericDaoSupport.searchForList(sentence, queryFilter.parameters());
        
	}
	
	/* (non-Javadoc)
	 * @see com.demo2do.fms.admin.service.report.ReportService#count(com.demo2do.fms.admin.entity.search.report.TransportRevenueScheduleSearch)
	 */
	public int count(TransportRevenueScheduleReportSearch search) {
	    String sentence = search.buildCountTemplate();
        Map<String, Object> parameters = search.buildParameters();
        return fmsJdbcSupport.queryForInt(sentence, parameters);
	}
	
	/* (non-Javadoc)
	 * @see com.demo2do.fms.admin.service.report.ReportService#search(com.demo2do.fms.admin.entity.search.report.TransportRevenueScheduleSearch, com.demo2do.core.entity.page.Page)
	 */
    public List<Map<String, Object>> search(TransportRevenueScheduleReportSearch search, Page page) {
	    
	    // 1. calculate page
        Integer beginIndex = page.getBeginIndex() + 1;
        search.setBeginIndex(beginIndex);
        
        Integer endIndex = page.getCurrentPage() * page.getEveryPage();
        search.setEndIndex(endIndex);
	    
	    // 1. build parameters
        String sentence = search.buildSentenceTemplate();
        Map<String, Object> parameters = search.buildParameters();
        
        // 2. do query
        List<Map<String, Object>> result = fmsJdbcSupport.queryForList(sentence, parameters, search.buildRowMapper());
        page.calculate();
        return result;
	    
	}
	
}
